package com.monkey.luffer.springboot.demo.basis.kcc.test.majiang;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @author jiahong.liu
 */
@Data
public class Player {
    PlayerHand playerHand = new PlayerHand();
    String name;
    boolean isManual;

    public Player (String name) {
        this.name = name;
    }

    public Player (String name, boolean isManual) {
        this.isManual = isManual;
        this.name = name;
    }

    public Status checkIfGetCard(Majiang.Card card, boolean isZimo) throws InterruptedException {
        if (isManual) {
            return checkIfGetCardByManual(card, isZimo);
        }

        // 先检查是否胡牌
        if (BaseRule.isHu(playerHand, card)) {
            if (isZimo) {
                System.out.println(name + ": 自摸" + card.printCard());
            } else {
                System.out.println(name + ": 放炮，胡牌");
            }

            return Status.HU;
        }

        // 检查牌中的kez和jiang
        playerHand.setJiang(getJiang(playerHand.getAll()));
        playerHand.setKez(getKe(playerHand.getAll()));
        // 去掉对中的刻子
        for(int i = 0; i < playerHand.getJiang().size(); i++) {
            int jiang = playerHand.getJiang().get(i);
            if (playerHand.getKez().contains(jiang)) {
                playerHand.getJiang().remove(i);
                if ( playerHand.getJiang().size() <= i) {
                    break;
                }
            }
        }

        // 有扛必杠
        if (playerHand.getKez().contains(card.getNumber() + card.getSuit().getSalt())) {
            if (!isZimo) {
                System.out.println(name + ":杠! " + card.printCard(4));
            }
            // 删除所有杠掉的牌
            playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
            playerHand.setCardNum(playerHand.cardNum - 3);
            return Status.GANG;
        }


        if (!isZimo) {
            // 有多余的对则碰
            if (playerHand.getJiang().size() >= 2 && playerHand.getJiang().contains(card.getNumber() + card.getSuit().getSalt())) {
                System.out.println(name + ": 碰！" + card.printCard(3));
                playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                playerHand.setCardNum(playerHand.cardNum - 2);
                return Status.PENG;
            }
        } else {
            // 需要打出一张牌
            playerHand.putInCard(card);
        }
        return Status.PASS;

    }

    public Status checkIfGetCardByManual(Majiang.Card card, boolean isZimo) throws InterruptedException {
        if (isZimo) {
            Thread.sleep(1000);
            System.out.println("您的手牌为：" + this.playerHand.printCard() + "摸到的牌为：" + card.printCard());
        }

        // 先检查是否胡牌
        if (BaseRule.isHu(playerHand, card)) {
            System.out.println("您的手牌为：" + this.playerHand.printCard());
            System.out.println("您已胡牌，输入 Y-胡，N-不胡");
            Scanner scanner = new Scanner(System.in);
            String line = scanner.nextLine();
            if ("Y".equals(line)) {
                return Status.HU;
            }
            return Status.HU;
        }

        // 检查牌中的kez和jiang
        playerHand.setJiang(getJiang(playerHand.getAll()));
        playerHand.setKez(getKe(playerHand.getAll()));
        // 去掉对中的刻子
        for(int i = 0; i < playerHand.getJiang().size(); i++) {
            int jiang = playerHand.getJiang().get(i);
            if (playerHand.getKez().contains(jiang)) {
                playerHand.getJiang().remove(i);
                if ( playerHand.getJiang().size() <= i) {
                    break;
                }
            }
        }

        if (playerHand.getKez().contains(card.getNumber() + card.getSuit().getSalt())) {
            System.out.println("您的手牌为：" + this.playerHand.printCard());
            System.out.println("您可以杠或碰"  + card.printCard() + "输入 G-杠，Y-碰，P-pass");
            Scanner scanner = new Scanner(System.in);
            String line = scanner.nextLine();
            // 删除所有杠掉的牌
            if ("G".equalsIgnoreCase(line)) {
                System.out.println(name + ": 杠！" + card.printCard(4));
                playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                playerHand.setCardNum(playerHand.cardNum - 3);
                return Status.GANG;
            } else if ("Y".equalsIgnoreCase(line)){
                System.out.println(name + ": 碰！" + card.printCard(3));
                playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                playerHand.setCardNum(playerHand.cardNum - 2);
                return Status.PENG;
            } else {
                return Status.PASS;
            }
        }


        if (!isZimo) {
            // 有多余的对则碰
            if (playerHand.getJiang().size() >= 1 && playerHand.getJiang().contains(card.getNumber() + card.getSuit().getSalt())) {
                System.out.println("您的手牌为：" + this.playerHand.printCard());
                System.out.println("您可以碰 "  + card.printCard() + "输入 Y-碰，P-pass");
                Scanner scanner = new Scanner(System.in);
                String line = scanner.nextLine();
                // 删除所有杠掉的牌
                if ("Y".equalsIgnoreCase(line)) {
                    System.out.println(name + ": 碰！" + card.printCard(3));
                    playerHand.getAll().removeIf(integer -> integer.equals(card.getNumber() + card.getSuit().getSalt()));
                    playerHand.setCardNum(playerHand.cardNum - 2);
                    return Status.PENG;
                } else {
                    return Status.PASS;
                }
            }
        } else {
            playerHand.putInCard(card);
        }
        return Status.PASS;

    }


    /**
     * 获取牌组中所有的“将”
     *
     * @param cards 牌组
     * @return 所有的“将”组成的数组
     */
    private static List<Integer> getJiang(List<Integer> cards) {
        List<Integer> jiang = new ArrayList<>();
        if (null != cards && cards.size() > 1) {
            for (int i = 0; i < cards.size() - 1; i++) {
                if (cards.get(i).equals(cards.get(i + 1))) {
                    jiang.add(cards.get(i));
                    i++;
                }
            }
        }
        return jiang;
    }

    /**
     * 去掉牌组中所有的刻子
     *
     * @param cards 牌组
     */
    private static List<Integer> getKe(List<Integer> cards) {
        List<Integer> ke = new ArrayList<>();
        for (int i = 0; i < cards.size() - 2; i++) {
            if (cards.get(i) .equals(cards.get(i + 1))  && cards.get(i).equals(cards.get(i + 2))) {
                ke.add(cards.get(i));
            }
        }
        return ke;
    }

    public void putOutCard(Majiang.Card card) {
        this.playerHand.removeCard(card);
    }

    public Majiang.Card putOutCard(List<Integer> all) {
        // 先删除刻子，再顺子，再删除一对，剩下的一个个遍历
        all = removeAllKe(all);
        all = removeAllShun(all);
        all = removeOneJiang(all);
        Integer temp = 0;
        Majiang.Card card = null;
        for (int i = 0; i < all.size() - 1; i++) {
            if (all.get(i).equals(all.get(i + 1))) {
                i++;
                continue;
            }

            if((all.get(i) + 1) == (all.get(i + 1))) {
                i++;
                continue;
            }

            temp = all.get(i);
            playerHand.removeCard(temp);
            card = Majiang.Card.getCard(temp);
            break;
        }

        if (temp.equals(0)) {
            // 如果找不到手上可以打的牌，则随便打一张
            card = Majiang.Card.getCard(playerHand.getAll().get(0));
            playerHand.removeCard(playerHand.getAll().get(0));
        }
        return card;
    }


    public boolean hasCard(Majiang.Card card) {
        return this.getPlayerHand().hasCard(card);
    }

    /**
     * 去掉牌组中所有的刻子
     *
     */
    public static List<Integer> removeAllKe(List<Integer> all) {
        List<Integer> tmp = new ArrayList<>(all);
        for (int i = 0; i < all.size() - 2; i++) {
            if (all.get(i).equals(all.get(i + 1))  && all.get(i + 1).equals(all.get(i + 2))) {
                Integer ele = all.get(i);
                tmp.removeIf(integer -> integer.equals(ele));
            }
        }
        return tmp;
    }

    /**
     * 去掉牌组中所有的顺子
     *
     */
    private static List<Integer> removeAllShun(List<Integer> all) {
        List<Integer> tmp = new ArrayList<>(all);
        for (int i = 0; i < all.size() - 2; i++) {
            if ((all.get(i) + 1) == (all.get(i + 1)) && all.get(i + 1) + 1 == all.get(i + 2)) {
                tmp.remove(all.get(i));
                tmp.remove(all.get(i + 1));
                tmp.remove(all.get(i + 2));
                i += 2;
            }
        }
        return tmp;
    }

    private static List<Integer> removeOneJiang(List<Integer> all) {
        List<Integer> tmp = new ArrayList<>(all);
        for (int i = 0; i < all.size() - 1; i++) {
            if (all.get(i).equals(all.get(i + 1))) {
                Integer ele = all.get(i);
                tmp.removeIf(integer -> integer.equals(ele));
            }
        }
        return tmp;
    }

    @AllArgsConstructor
    public enum Status {
        /**
         *
         */
        EAT("0", "吃"),
        PENG("1", "碰"),
        HU("2", "胡"),
        GANG("3", "杠"),
        PASS("4", "");

        String code;
        String value;
    }
}
